package edu.usm.roberge.ui;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

import edu.usm.roberge.model.StockQuoteData;
import edu.usm.roberge.model.StockStore;
import edu.usm.roberge.webservice.StockQuoteClient;
import edu.usm.roberge.webservice.StockQuoteClient.StockQuoteClientException;

/**
 * Swing Worker that periodically checks for updated stock quote information
 * NOTE: This class is "always" running, in other words it doesn't actually
 * "complete" until the application is terminated
 */
public class QuoteRetrieverWorker extends SwingWorker<Void, StockQuoteData> {

	private static final int MILLISECONDS_IN_SECOND = 1000;
	private static final int MINUTES_TO_DELAY = 5;
	private static final int SECONDS_IN_MINUTE = 60;
	private static final int REFRESH_DELAY_IN_MILLISECONDS = (SECONDS_IN_MINUTE * MINUTES_TO_DELAY) * MILLISECONDS_IN_SECOND;
	
	private final StockQuoteClient client;
	private Date lastTimeUpdated;
	private final Properties stocks;
	private final StockStore store;
	private final Listener listener;

	public QuoteRetrieverWorker(Properties stocks, StockStore store, Listener listener) {
		client = new StockQuoteClient();
		this.stocks = stocks;
		this.store = store;
		this.listener = listener;
		lastTimeUpdated = Calendar.getInstance().getTime();
		lastTimeUpdated.setTime(0);
	}
	
	public interface Listener {
		void onUpdatingStockInformationStarted();
		
		void onUpdatingStockInformationCompleted();
	}
	
	@Override
	protected Void doInBackground() throws Exception {
		while(true) {
			Date currentTime = Calendar.getInstance().getTime();
			if (currentTime.getTime() - lastTimeUpdated.getTime() > REFRESH_DELAY_IN_MILLISECONDS) {
				lastTimeUpdated = currentTime;
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						listener.onUpdatingStockInformationStarted();
					}
				});
				
				updateStockInformation();
			
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						listener.onUpdatingStockInformationCompleted();
					}
				});
			} else {
				Thread.sleep(1000);
			}
		}
	}

	private void updateStockInformation() {
		for(Object symbol : stocks.values()) {
			try {
				StockQuoteData data = client.getStockQuote(symbol.toString());
				this.publish(data);
			} catch (StockQuoteClientException e) {
			}
		}
	}

	@Override
	protected void process(List<StockQuoteData> chunks) {
		for(StockQuoteData data : chunks) {
			store.setStockQuoteData(data);
		}
	}

}
